package com.harmony.pilot.knowledge.service;

import com.harmony.pilot.knowledge.entity.GnTarget;
import com.harmony.pilot.knowledge.entity.GnBuildFile;
import com.harmony.pilot.knowledge.repository.GnBuildFileRepository;
import com.harmony.pilot.knowledge.repository.GnTargetRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 依赖分析服务
 * 分析代码的依赖关系，验证GN文件依赖，查找缺失的依赖
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DependencyAnalysisService {
    
    private final WebClient codeQLClient;
    private final GnBuildFileRepository gnBuildFileRepository;
    private final GnTargetRepository gnTargetRepository;
    
    // Include语句的正则表达式
    private static final Pattern INCLUDE_PATTERN = Pattern.compile(
        "^\\s*#include\\s+[\"<]([^>\"]+)[>\"]"
    );
    
    public DependencyAnalysisService(
            @org.springframework.beans.factory.annotation.Value("${knowledge.codeql.data-service-url:http://localhost:8085}") 
            String dataServiceUrl,
            GnBuildFileRepository gnBuildFileRepository,
            GnTargetRepository gnTargetRepository) {
        this.codeQLClient = WebClient.builder()
                .baseUrl(dataServiceUrl)
                .build();
        this.gnBuildFileRepository = gnBuildFileRepository;
        this.gnTargetRepository = gnTargetRepository;
    }
    
    /**
     * 分析文件的依赖关系
     */
    public DependencyAnalysisResult analyzeDependencies(String filePath, String code) {
        log.info("Analyzing dependencies for: {}", filePath);
        
        DependencyAnalysisResult result = new DependencyAnalysisResult();
        result.setFilePath(filePath);
        
        // 1. 提取Include语句
        List<String> includes = extractIncludes(code);
        result.setIncludes(includes);
        
        // 2. 推断模块和GN依赖
        List<String> requiredModules = new ArrayList<>();
        List<String> gnDepSuggestions = new ArrayList<>();
        
        for (String include : includes) {
            String module = inferModuleFromInclude(include);
            if (module != null && !module.isEmpty()) {
                requiredModules.add(module);
                
                String gnDep = inferGnDepFromModule(module);
                if (gnDep != null && !gnDepSuggestions.contains(gnDep)) {
                    gnDepSuggestions.add(gnDep);
                }
            }
        }
        
        result.setRequiredModules(requiredModules);
        result.setSuggestions(gnDepSuggestions);
        
        return result;
    }
    
    /**
     * 验证GN文件依赖
     */
    public GnDependencyValidationResult validateGnDependencies(
            String gnFilePath, 
            List<String> sourceFiles) {
        
        log.info("Validating GN dependencies: {}, sources: {}", gnFilePath, sourceFiles.size());
        
        GnDependencyValidationResult result = new GnDependencyValidationResult();
        result.setGnFilePath(gnFilePath);
        
        // 1. 查找GN文件
        Optional<GnBuildFile> gnFileOpt = gnBuildFileRepository.findByFilePath(gnFilePath);
        if (gnFileOpt.isEmpty()) {
            result.setValid(false);
            result.setError("GN file not found in knowledge base");
            return result;
        }
        
        GnBuildFile gnFile = gnFileOpt.get();
        
        // 2. 获取所有源文件的include
        Set<String> allIncludes = new HashSet<>();
        // TODO: 从知识库读取源文件内容并提取include
        
        // 3. 获取当前GN target的deps
        Set<String> currentDeps = new HashSet<>();
        for (GnTarget target : gnFile.getTargets()) {
            if (target.getDeps() != null) {
                try {
                    // 解析JSON格式的deps
                    List<String> deps = parseJsonList(target.getDeps());
                    currentDeps.addAll(deps);
                } catch (Exception e) {
                    log.warn("Failed to parse deps: {}", target.getDeps(), e);
                }
            }
        }
        
        result.setCurrentDeps(new ArrayList<>(currentDeps));
        
        // 4. 从include推断需要的依赖
        List<String> requiredDeps = allIncludes.stream()
                .map(this::inferGnDepFromInclude)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        
        // 5. 找出缺失的依赖
        List<String> missingDeps = requiredDeps.stream()
                .filter(dep -> !currentDeps.contains(dep))
                .collect(Collectors.toList());
        
        result.setMissingDeps(missingDeps);
        result.setValid(missingDeps.isEmpty());
        
        return result;
    }
    
    /**
     * 查找缺失的依赖
     */
    public List<String> findMissingDependencies(String gnFilePath, List<String> includes) {
        log.info("Finding missing dependencies: {}, includes: {}", gnFilePath, includes.size());
        
        // 1. 获取当前GN文件的依赖
        Set<String> currentDeps = getCurrentGnDeps(gnFilePath);
        
        // 2. 从include推断需要的依赖
        List<String> requiredDeps = includes.stream()
                .map(this::inferGnDepFromInclude)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        
        // 3. 找出缺失的依赖
        return requiredDeps.stream()
                .filter(dep -> !currentDeps.contains(dep))
                .collect(Collectors.toList());
    }
    
    /**
     * 从代码中提取Include语句
     */
    private List<String> extractIncludes(String code) {
        List<String> includes = new ArrayList<>();
        
        String[] lines = code.split("\n");
        for (String line : lines) {
            Matcher matcher = INCLUDE_PATTERN.matcher(line);
            if (matcher.find()) {
                String includePath = matcher.group(1);
                // 过滤系统头文件
                if (!isSystemHeader(includePath)) {
                    includes.add(includePath);
                }
            }
        }
        
        return includes;
    }
    
    /**
     * 判断是否为系统头文件
     */
    private boolean isSystemHeader(String includePath) {
        // 系统头文件通常用尖括号，但这里我们已经提取了路径
        // 可以根据路径特征判断
        return includePath.startsWith("/usr/") ||
               includePath.equals("stdlib.h") ||
               includePath.equals("string.h") ||
               includePath.equals("iostream") ||
               includePath.startsWith("c++");
    }
    
    /**
     * 从Include路径推断模块
     * 例如: "foundation/arkui/napi/napi_common.h" -> "foundation/arkui/napi"
     */
    private String inferModuleFromInclude(String includePath) {
        // 移除文件扩展名
        String path = includePath.replaceAll("\\.[^.]*$", "");
        
        // 提取模块路径（通常是前3-4级目录）
        String[] parts = path.split("/");
        if (parts.length >= 2) {
            // 组合前几级作为模块路径
            int moduleDepth = Math.min(3, parts.length);
            return String.join("/", Arrays.copyOf(parts, moduleDepth));
        }
        
        return null;
    }
    
    /**
     * 从模块路径推断GN依赖路径
     * 例如: "foundation/arkui/napi" -> "//foundation/arkui/napi:napi"
     */
    private String inferGnDepFromModule(String module) {
        if (module == null || module.isEmpty()) {
            return null;
        }
        
        // 尝试从知识库查找对应的GN target
        // 先查找BUILD.gn文件
        Optional<GnBuildFile> gnFileOpt = gnBuildFileRepository.findByFilePathContaining(module);
        if (gnFileOpt.isPresent()) {
            GnBuildFile gnFile = gnFileOpt.get();
            // 获取第一个target作为默认依赖
            if (!gnFile.getTargets().isEmpty()) {
                GnTarget target = gnFile.getTargets().get(0);
                // 构建GN路径: //module/path:target_name
                String gnPath = "//" + module + ":" + target.getTargetName();
                return gnPath;
            }
        }
        
        // 如果找不到，使用启发式规则
        // 提取最后一个路径段作为target名称
        String[] parts = module.split("/");
        if (parts.length > 0) {
            String targetName = parts[parts.length - 1];
            return "//" + module + ":" + targetName;
        }
        
        return null;
    }
    
    /**
     * 从Include路径直接推断GN依赖
     */
    private String inferGnDepFromInclude(String includePath) {
        String module = inferModuleFromInclude(includePath);
        return module != null ? inferGnDepFromModule(module) : null;
    }
    
    /**
     * 获取当前GN文件的依赖
     */
    private Set<String> getCurrentGnDeps(String gnFilePath) {
        Set<String> deps = new HashSet<>();
        
        Optional<GnBuildFile> gnFileOpt = gnBuildFileRepository.findByFilePath(gnFilePath);
        if (gnFileOpt.isPresent()) {
            GnBuildFile gnFile = gnFileOpt.get();
            for (GnTarget target : gnFile.getTargets()) {
                if (target.getDeps() != null) {
                    try {
                        List<String> targetDeps = parseJsonList(target.getDeps());
                        deps.addAll(targetDeps);
                    } catch (Exception e) {
                        log.warn("Failed to parse deps", e);
                    }
                }
            }
        }
        
        return deps;
    }
    
    /**
     * 解析JSON列表
     */
    private List<String> parseJsonList(String json) {
        List<String> list = new ArrayList<>();
        if (json == null || json.trim().isEmpty()) {
            return list;
        }
        
        try {
            // 简单的JSON数组解析（实际应该使用Jackson）
            String content = json.trim();
            if (content.startsWith("[") && content.endsWith("]")) {
                content = content.substring(1, content.length() - 1);
                String[] items = content.split(",");
                for (String item : items) {
                    String trimmed = item.trim().replaceAll("^\"|\"$", "");
                    if (!trimmed.isEmpty()) {
                        list.add(trimmed);
                    }
                }
            }
        } catch (Exception e) {
            log.warn("Failed to parse JSON list: {}", json, e);
        }
        
        return list;
    }
    
    // DTO类
    @lombok.Data
    public static class DependencyAnalysisResult {
        private String filePath;
        private List<String> includes;
        private List<String> requiredModules;
        private List<String> suggestions;  // GN依赖建议
        private List<String> currentDeps;
        private List<String> missingDeps;
    }
    
    @lombok.Data
    public static class GnDependencyValidationResult {
        private String gnFilePath;
        private boolean valid;
        private String error;
        private List<String> currentDeps;
        private List<String> missingDeps;
        private List<String> warnings;
    }
}

